/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : DevSocSub.c
 * Author        : joki.zhu
 * Date          : 2020-07-03
 *
 * Record        :
 * 1.Date        : 2020-07-03
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include "app_common.h"
#include "DevSocSub.h"
#include "McuSoc.h"
#include "hi_hal_syslink.h"

#define SOCSUB_UPGRADE_BLOCK_SIZE    (256)

typedef struct {
    char bUpgradeRun;
    unsigned int offset;
    unsigned int pktSize;
}SocSubUpgradeContext;

static SocSubUpgradeContext g_socSubUpgCtx = {
    .bUpgradeRun    = 0,
    .offset         = 0,
    .pktSize        = 0,
};

int SocSubSetLedState(unsigned char value)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_led_state(value);
#else
    return mcusoc_set_led_state(value);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetPirSwitch(char bEnable)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_pir(bEnable);
#else
    return mcusoc_set_pir_switch(bEnable);
#endif /* HISYSLINK_ENABLE */
}

int SocSubGetPirSwitch(char *bEnable)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_get_pir(bEnable);

#endif /* HISYSLINK_ENABLE */
}

int SocSubGetPirSensitivity(int *pValue)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_pir_sensitivity(pValue);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetPirSensitivity(int value)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_pir_sensitivity(value);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetPirDelayWakeupTime(PIR_DELAY_WAKEUP_ATTR_S stPirDelayAttr)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_pir_delay_wakeup_time(stPirDelayAttr);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetPirDelayWakeupTime(PIR_DELAY_WAKEUP_ATTR_S *pstPirDelayAttr)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_pir_delay_wakeup_time(pstPirDelayAttr);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetBatteryStatus(BATTERY_STATUS_S *pstBatStatus)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_get_battery_status(pstBatStatus);
#else
    return mcusoc_get_battery_status(pstBatStatus);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetWakeUpType(SYSTEM_WAKEUP_TYPE_E *pWakeUpType)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_get_wakeup_type(pWakeUpType);
#else
    return mcusoc_get_wakeup_type(pWakeUpType);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetTime(SYSTEM_TIME *pstSysTime)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_get_time(pstSysTime);
#else
    return mcusoc_get_time(pstSysTime);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetTime(SYSTEM_TIME stSysTime)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_time(stSysTime);
#else
    return mcusoc_set_time(stSysTime);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetReset(char *reason)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_reset(reason);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief WiFi模块上电
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWifiPowerOn(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wifi_power_on();
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief WiFi模块下电
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWifiPowerOff(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wifi_power_off();
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 设置WiFi电源开关
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWifiPowerSwitch(unsigned char switchState)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wifi_power_switch(switchState);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 主控下电
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetMainSocPowerOff(void)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_system_mode(HI_SYSLINK_SYS_MODE_STANDBY);
#else
    return mcusoc_set_mainsoc_power_off();
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 主控维持自身电源
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetMainSocKeepPower(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_mainsoc_keep_power();
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 设置MCU看门狗使能状态
 *
 * @param[in] bEnalbe 使能状态 0:禁用 1:使能
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWdgState(char bEnable)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wdg_state(bEnable);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 获取MCU看门狗使能状态
 *
 * @param[in] pState 状态 0:未使能 1:已使能
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubGetWdgState(char *pState)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_wdg_state(pState);
#endif /* HISYSLINK_ENABLE */
}

/**
 * @brief 配置MCU看门狗周期
 *
 * @param[in] time 看门狗周期时间
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWdgPeriod(AV_U32 time)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wdg_period(time);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief MCU喂狗
 *
 * @param 无
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 无
 */
int SocSubSetWdgFeed(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wdg_feed();
#endif /* HISYSLINK_ENABLE */

}


int SocSubSetWifiState(char state)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wifi_state(state);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetWifiState(char *pState)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_wifi_state(pState);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetSysConfig(SOCSUB_SYS_CONFIG_S stMcuSysConfig)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_sys_config(stMcuSysConfig);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetSysConfig(SOCSUB_SYS_CONFIG_S *pstMcuSysConfig)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_sys_config(pstMcuSysConfig);
#endif /* HISYSLINK_ENABLE */

}

int SocSubSetAlarmWakeup(SOCSUB_ALARM_WAKEUP_ATTR_S stAlarmWakeupAttr)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_alarm_wakeup(stAlarmWakeupAttr);
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetAlarmWakeup(SOCSUB_ALARM_WAKEUP_ATTR_S *pstAlarmWakeupAttr)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_alarm_wakeup(pstAlarmWakeupAttr);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 配置MCU监控SOC启动的时间
 *
 * @param[in] timeSec 监控描述
 * 
 * @return |0|未升级| |非0|失败|
 *
 * @attention 超过监控时间,即从启动到设置的监控时间内,都没有和MCU通信,则MCU会重启SOC
 */
int SocSubSetMainSocStartDetectTime(int timeSec)
{
#ifdef HISYSLINK_ENABLE
    LOGD("unsupport\n");
    return 0;
#else
    return mcusoc_set_mainsoc_start_detect_time(timeSec);
#endif /* HISYSLINK_ENABLE */

}

int SocSubCheckIsSupportUpdate(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_check_is_support_update();
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetVersion(char *pVersion)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_get_version(pVersion);
#else
    return mcusoc_get_version(pVersion);
#endif /* HISYSLINK_ENABLE */

}

/**
 * @brief 清除唤醒事件
 *
 * @param 无
 * 
 * @return |0|成功| |非0|失败|
 *
 * @attention 通知给MCU清除唤醒状态,另休眠时mcu也会主动清除,防止下次唤醒获取唤醒类型不正确
 */
int SocSubSetClearWakeupEvent(void)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_set_wakeup_event_clear();
#endif /* HISYSLINK_ENABLE */

}

int SocSubGetTemperature(float *pTempValue)
{
#ifdef HISYSLINK_ENABLE
    
#else
    return mcusoc_get_temperature(pTempValue);
#endif /* HISYSLINK_ENABLE */

}

int SocSubInit(void)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_init();
#else
    return mcusoc_init();
#endif /* HISYSLINK_ENABLE */

}

int SocSubDeinit(void)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_deinit();
#else
    return mcusoc_deinit();
#endif /* HISYSLINK_ENABLE */

}


int SocSubWifiConnect(char *ssid, char *pwd, WIFI_ENCRYPT_TYPE_E enEncryptType)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_wifi_connect(ssid, pwd, enEncryptType);
#endif /* HISYSLINK_ENABLE */
}

int SocSubWifiDisconnect(void)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_wifi_disconnect();
#endif /* HISYSLINK_ENABLE */
}


int SocSubWifiGetStatus(WIFI_STATUS_INFO_S *pstStatusInfo)
{
#ifdef HISYSLINK_ENABLE
    AV_RETURN_IF_PTR_NULL(pstStatusInfo, AV_FAILURE);
    
    int ret = 0;
    HI_SYSLINK_WIFI_STATUS stWifiStatus;

    memset(&stWifiStatus, 0, sizeof(stWifiStatus));
    ret = wifisoc_get_wifi_status(&stWifiStatus);
    AV_RETURN_WITH_INFO_IF_FAIL(ret, AV_FAILURE, "wifisoc_get_wifi_status");

    snprintf(pstStatusInfo->ssid, sizeof(pstStatusInfo->ssid), "%s", stWifiStatus.ssid);
    pstStatusInfo->signalLevel = stWifiStatus.rssi + 100;

    if (stWifiStatus.state == 1) {
        pstStatusInfo->connectionStatus = WIFI_CONNECTED;
    } else {
        pstStatusInfo->connectionStatus = WIFI_DISCONNECTED;
    }
#endif /* HISYSLINK_ENABLE */

    return AV_SUCCESS;
}


int SocSubSetSystemMode(HI_SYSLINK_SYS_MODE enSysMode)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_system_mode(enSysMode);
#else
    return 0;
#endif
}

static SocSubUpgradeContext *socsub_get_upgrade_ctx(void)
{
    return &g_socSubUpgCtx;
}

int SocSubCheckIsUpgrading(void)
{
    return socsub_get_upgrade_ctx()->bUpgradeRun;
}

int SocSubUpgradeStart(char type, int pktSize, char *crc)
{
    AV_RETURN_IF_PTR_NULL(crc, AV_FAILURE);

    LOGI("sossub upgrade upgrade start! type:%d pktSize:%d crc:%s\n", type, pktSize, crc);
    
    int ret = 0;
    HI_SYSLINK_UPGRADE_START_MSG stUpgStartMsg = {0};   
    SocSubUpgradeContext *ctx = socsub_get_upgrade_ctx();

    if (type == 0) { /* boot */
        stUpgStartMsg.pktType = 0;
        stUpgStartMsg.pktSize = pktSize;
    } else { /* kernel */
        char kernelConfigCrc[12] = "";
        DevConfigGetMcuCrc(kernelConfigCrc, sizeof(kernelConfigCrc));
        if (strcmp(kernelConfigCrc, crc) == 0) {
            LOGW("wifi kernel crc is euqal, exit wifi kernel upgrade\n");
            return -1;
        }
        stUpgStartMsg.pktType = 1;
        stUpgStartMsg.pktSize = pktSize;
    }
    ctx->offset = 0;
    ctx->bUpgradeRun = 1;

    ret = wifisoc_upgrade_start(stUpgStartMsg);
    AV_RETURN_WITH_INFO_IF_EXPR_FALSE(ret == AV_SUCCESS, AV_FAILURE, "wifisoc_upgrade_start");

    ctx->offset = 0;
    ctx->pktSize = pktSize;
    
    return 0;
}

int SocSubUpgradeTransmit(unsigned char *buf, unsigned int size)
{
    AV_RETURN_IF_PTR_NULL(buf, AV_FAILURE);

    int ret = 0;
    HI_SYSLINK_UPGRADE_TRANSMIT_MSG stUpgTransMsg = {0};
    SocSubUpgradeContext *ctx = socsub_get_upgrade_ctx();

    int sendSize = 0;
    int sendOffset = 0;
    int remainSize = size;
    
    while (remainSize > 0)
    {
        sendSize = (remainSize > SOCSUB_UPGRADE_BLOCK_SIZE ) ? SOCSUB_UPGRADE_BLOCK_SIZE : remainSize;

        memset(&stUpgTransMsg, 0, sizeof(stUpgTransMsg));
        stUpgTransMsg.len = sendSize;
        stUpgTransMsg.offset = ctx->offset;
        memcpy(stUpgTransMsg.buf, buf + sendOffset, stUpgTransMsg.len);
        if (ctx->pktSize == (ctx->offset + sendSize)) {
            stUpgTransMsg.bFinished = 1;
            LOGI("sossub upgrade transmit finished!\n");
        }
        
//        LOGI("offset:%d len:%d bFinished:%d\n", stUpgTransMsg.offset, stUpgTransMsg.len, stUpgTransMsg.bFinished);
        ret = wifisoc_upgrade_transmit(stUpgTransMsg);
        AV_RETURN_WITH_INFO_IF_EXPR_FALSE(ret == AV_SUCCESS, AV_FAILURE, "wifisoc_upgrade_transmit");

        remainSize -= sendSize;
        sendOffset += sendSize;
        ctx->offset += sendSize;
    }
    
    return 0;
}

int SocSubUpgradeFinish(char *bootcrc, char *kernelcrc)
{
    LOGI("sossub upgrade finished!\n");

	DaemonUpgradeNotifyFinish();
	
    /* update wifi kernel crc to config */
    DevConfigSetMcuCrc(kernelcrc);

    return wifisoc_upgrade_finish();
}

int SocSubSetResetSwitch(char bEnable)
{
#ifdef HISYSLINK_ENABLE
    return wifisoc_set_reset_switch(bEnable);
#else
    return 0;
#endif /* HISYSLINK_ENABLE */
}


